package com.bdq.content.domain.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.bdq.common.enums.*;
import com.bdq.common.exception.ServerException;
import com.bdq.common.utils.StaticFileUtil;
import com.bdq.content.domain.model.agg.ContentAgg;
import com.bdq.content.domain.model.dto.ContentDetailDomainDTO;
import com.bdq.content.domain.model.dto.ContentDetailVoteOptionDomainDTO;
import com.bdq.content.domain.model.dto.ContentListDomainDTO;
import com.bdq.content.domain.model.dto.req.*;
import com.bdq.content.domain.model.value.ContentLocationValue;
import com.bdq.content.domain.model.value.ContentVoteOptionValue;
import com.bdq.content.domain.service.ContentDomainService;
import com.bdq.content.infrastructure.cache.ContentCache;
import com.bdq.content.infrastructure.persistence.mysql.pojo.Content;
import com.bdq.content.infrastructure.persistence.mysql.pojo.ContentLocation;
import com.bdq.content.infrastructure.persistence.mysql.pojo.ContentVoteOption;
import com.bdq.content.infrastructure.persistence.mysql.service.ContentLocationService;
import com.bdq.content.infrastructure.persistence.mysql.service.ContentService;
import com.bdq.content.infrastructure.persistence.mysql.service.ContentVoteOptionService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author malei
 * @date 2024-05-10 17:55
 */
@Service
public class ContentDomainServiceImpl implements ContentDomainService {

    @Resource
    private ContentService contentService;

    @Resource
    private ContentLocationService contentLocationService;

    @Resource
    private ContentVoteOptionService contentVoteOptionService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ContentAgg postContent(ContentPostReqDTO reqDTO) {
        // 1 校验
        if (reqDTO.getChannel() == ChannelEnum.MARKET.getCode()) {
            if (Objects.isNull(reqDTO.getCategoryId()) || StrUtil.isBlank(reqDTO.getCategoryName())) {
                throw new ServerException("请填写分类");
            }
            if (Objects.isNull(reqDTO.getPrice())) {
                throw new ServerException("请填写价格");
            }
        }
        if (reqDTO.getChannel() == ChannelEnum.GOVERNMENT.getCode()) {
            if (UserRoleEnum.COMMUNITY_ORGANIZATION.getCode() != reqDTO.getRole()) {
                throw new ServerException("完成基层群众性自治组织认证后方可发布该频道");
            }
            if (Objects.isNull(reqDTO.getCategoryId()) || StrUtil.isBlank(reqDTO.getCategoryName())) {
                throw new ServerException("请填写分类");
            }
            if (Objects.nonNull(reqDTO.getActivityType())) {
                if (Objects.isNull(reqDTO.getActivityBeginTime())) {
                    throw new ServerException("请填写活动开始时间");
                }
                if (Objects.isNull(reqDTO.getActivityEndTime())){
                    throw new ServerException("请填写活动结束时间");
                }
                if (reqDTO.getActivityBeginTime().isAfter(LocalDateTime.now())) {
                    throw new ServerException("开始时间不能早于当前时间");
                }
                if (reqDTO.getActivityEndTime().isBefore(LocalDateTime.now())) {
                    throw new ServerException("结束时间不能早于开始时间");
                }
                if (ActivityTypeEnum.VOTE.getCode() == reqDTO.getActivityType() && CollUtil.isEmpty(reqDTO.getVoteOptions())) {
                    throw new ServerException("投票活动请填写投票项");
                }
            }
        }

        // 2 保存
        // 2.1 内容
        Content content = Convert.convert(Content.class, reqDTO);
        if (StrUtil.isNotBlank(reqDTO.getPictures())) {
            List<String> pictureList = new ArrayList<>();
            String pictures = reqDTO.getPictures();
            for (String picture : pictures.split(",")) {
                pictureList.add(StaticFileUtil.domainCut(picture));
            }
            content.setPictures(String.join(",", pictureList));
        }
        if (Objects.nonNull(reqDTO.getCategoryId()) && StrUtil.isNotBlank(reqDTO.getCategoryName())) {
            content.setIsSetCategory(YesOrNoEnum.YES.getCode());
        }
        if (Objects.nonNull(reqDTO.getPrice())) {
            content.setIsSetPrice(YesOrNoEnum.YES.getCode());
        }
        if (Objects.nonNull(reqDTO.getActivityType())) {
            content.setIsSetActivity(YesOrNoEnum.YES.getCode());
        }
        contentService.save(content);
        // 2.2 所在地
        ContentLocation contentLocation = Convert.convert(ContentLocation.class, reqDTO.getLocation());
        contentLocation.setContentId(content.getId());
        contentLocationService.save(contentLocation);
        // 2.3 投票项
        if (CollUtil.isNotEmpty(reqDTO.getVoteOptions())) {
            List<ContentVoteOption> contentVoteOptions = Convert.toList(ContentVoteOption.class, reqDTO.getVoteOptions());
            for (ContentVoteOption contentVoteOption : contentVoteOptions) {
                contentVoteOption.setUserId(reqDTO.getUserId());
                contentVoteOption.setContentId(content.getId());
            }
            contentVoteOptionService.saveBatch(contentVoteOptions);
        }

        // 3 区域内容更新
        ContentCache.cityContentAdd(reqDTO.getLocation().getCityId(), content.getId());

        // 4 返回聚合对象
        ContentAgg contentAgg = new ContentAgg();
        contentAggFill(content.getId(), contentAgg);
        return contentAgg;
    }

    @Override
    public void contentAggFill(Long contentId, ContentAgg contentAgg) {
        // 1 查询内容
        Content content = contentService.getById(contentId);
        BeanUtils.copyProperties(content, contentAgg);

        // 2 查询位置
        ContentLocation contentLocation = contentLocationService.getByContentId(contentId);
        ContentLocationValue contentLocationValue = Convert.convert(ContentLocationValue.class, contentLocation);
        contentAgg.setContentLocation(contentLocationValue);

        // 3 查询投票项
        List<ContentVoteOption> contentVoteOptionList = contentVoteOptionService.listByContentId(contentId);
        if (CollUtil.isEmpty(contentVoteOptionList)) {
            return;
        }
        List<ContentVoteOptionValue> contentVoteOptionValues = Convert.toList(ContentVoteOptionValue.class, contentVoteOptionList);
        contentAgg.setContentVoteOptions(contentVoteOptionValues);
    }

    @Override
    public ContentDetailDomainDTO detail(ContentDetailReqDTO reqDTO, ContentAgg contentAgg) {
        ContentDetailDomainDTO contentDetailDomainDTO = new ContentDetailDomainDTO();
        // 1 是否自己的
        if (contentAgg.getUserId().equals(reqDTO.getCurrentUserId())) {
            contentDetailDomainDTO.setIsOwn(YesOrNoEnum.YES.getCode());
        }else {
            contentDetailDomainDTO.setIsOwn(YesOrNoEnum.NO.getCode());
        }
        // 2 内容基本信息
        BeanUtils.copyProperties(contentAgg, contentDetailDomainDTO);
        // 3 图片
        List<String> picList = new ArrayList<>();
        for (String pic : contentAgg.getPictures().split(",")) {
            picList.add(StaticFileUtil.domainConcat(pic));
        }
        contentDetailDomainDTO.setPictures(picList);
        // 4 活动状态
        LocalDateTime now = LocalDateTime.now();
        if (contentAgg.getActivityBeginTime().isBefore(now)) {
            contentDetailDomainDTO.setActivityStatus(ActivityStatusEnum.NOT_STARTED.getCode());
        }else if (contentAgg.getActivityEndTime().isAfter(now)) {
            contentDetailDomainDTO.setActivityStatus(ActivityStatusEnum.ENDED.getCode());
        }else {
            contentDetailDomainDTO.setActivityStatus(ActivityStatusEnum.IN_PROGRESS.getCode());
        }
        // 5 位置
        contentDetailDomainDTO.setLocationName(contentAgg.getContentLocation().getVillageName());
        contentDetailDomainDTO.setLongitude(new BigDecimal("39.907325"));
        contentDetailDomainDTO.setLatitude(new BigDecimal("116.391422"));
        // 6 发布时间
        contentDetailDomainDTO.setPostTime(postTimeConvert(contentAgg.getCreateTime()));
        // 7 互动基本信息
        BeanUtils.copyProperties(reqDTO, contentDetailDomainDTO);
        // 8 投票数据
        List<ContentVoteOptionValue> contentVoteOptions = contentAgg.getContentVoteOptions();
        if (CollUtil.isEmpty(contentVoteOptions)) {
            return contentDetailDomainDTO;
        }
        Map<Long, ContentVoteOptionValue> voteOptionValueMapMap = contentVoteOptions.stream().collect(Collectors.toMap(ContentVoteOptionValue::getId, e -> e));
        List<ContentDetailVoteOptionDomainDTO> contentDetailVoteOptionDomainDTOS = Convert.toList(ContentDetailVoteOptionDomainDTO.class, reqDTO.getVoteOptions());
        for (ContentDetailVoteOptionDomainDTO contentDetailVoteOptionDomainDTO : contentDetailVoteOptionDomainDTOS) {
            contentDetailVoteOptionDomainDTO.setOptionContent(voteOptionValueMapMap.get(contentDetailVoteOptionDomainDTO.getId()).getOptionContent());
        }
        contentDetailDomainDTO.setVoteOptions(contentDetailVoteOptionDomainDTOS);
        return contentDetailDomainDTO;
    }

    @Override
    public List<ContentListDomainDTO> listContent(ContentListReqDTO reqDTO) {
        List<Content> contentList = contentService.listByIds(reqDTO.getContentIds());
        Map<Long, Content> contentMap = contentList.stream().collect(Collectors.toMap(Content::getId, e -> e));
        List<ContentLocation> contentLocationList = contentLocationService.listByContentIds(reqDTO.getContentIds());
        Map<Long, ContentLocation> contentLocationMap = contentLocationList.stream().collect(Collectors.toMap(ContentLocation::getContentId, e -> e));

        List<ContentListUserReqDTO> contentUsers = reqDTO.getContentUsers();
        Map<Long, ContentListUserReqDTO> contentUserMap = contentUsers.stream().collect(Collectors.toMap(ContentListUserReqDTO::getId, e -> e));

        List<ContentListInteractionReqDTO> interactions = reqDTO.getInteractions();
        Map<Long, ContentListInteractionReqDTO> interactionMap = interactions.stream().collect(Collectors.toMap(ContentListInteractionReqDTO::getContentId, e -> e));

        List<ContentListDomainDTO> contentListDomainDTOS = new ArrayList<>();
        for (Long contentId : reqDTO.getContentIds()) {
            Content content = contentMap.get(contentId);
            ContentListUserReqDTO contentUser = contentUserMap.get(content.getUserId());
            ContentListInteractionReqDTO contentListInteractionReqDTO = interactionMap.get(contentId);

            ContentListDomainDTO contentListDomainDTO = new ContentListDomainDTO();
            BeanUtils.copyProperties(content, contentListDomainDTO);
            // 1 是否自己的
            if (content.getUserId().equals(reqDTO.getUserId())) {
                contentListDomainDTO.setIsOwn(YesOrNoEnum.YES.getCode());
            }else {
                contentListDomainDTO.setIsOwn(YesOrNoEnum.NO.getCode());
            }
            // 2 作者信息
            contentListDomainDTO.setNickName(contentUser.getNickName());
            contentListDomainDTO.setAvatar(StaticFileUtil.domainConcat(contentUser.getAvatar()));
            // 3 图片
            List<String> picList = new ArrayList<>();
            if (StrUtil.isNotBlank(content.getPictures())) {
                for (String pic : content.getPictures().split(",")) {
                    picList.add(StaticFileUtil.domainConcat(pic));
                }
            }
            contentListDomainDTO.setPictures(picList);
            // 4 活动状态
            LocalDateTime now = LocalDateTime.now();
            if (content.getActivityBeginTime().isBefore(now)) {
                contentListDomainDTO.setActivityStatus(ActivityStatusEnum.NOT_STARTED.getCode());
            }else if (content.getActivityEndTime().isAfter(now)) {
                contentListDomainDTO.setActivityStatus(ActivityStatusEnum.ENDED.getCode());
            }else {
                contentListDomainDTO.setActivityStatus(ActivityStatusEnum.IN_PROGRESS.getCode());
            }
            // 5 位置
            contentListDomainDTO.setLocationName(contentLocationMap.get(contentId).getVillageName());
            contentListDomainDTO.setLongitude(new BigDecimal("39.907325"));
            contentListDomainDTO.setLatitude(new BigDecimal("116.391422"));
            // 6 发布时间
            contentListDomainDTO.setPostTime(postTimeConvert(content.getCreateTime()));
            // 7 互动基本信息
            BeanUtils.copyProperties(contentListInteractionReqDTO, contentListDomainDTO);
            contentListDomainDTOS.add(contentListDomainDTO);
        }
        return contentListDomainDTOS;
    }

    /**
     * 评论时间转换
     *
     * @param time
     * @return
     */
    private String postTimeConvert(LocalDateTime time) {

        LocalDateTime now = LocalDateTime.now();
        Duration duration = Duration.between(time, now);

        long seconds = duration.getSeconds();
        long minutes = duration.toMinutes();
        long hours = duration.toHours();
        long days = duration.toDays();

        if (seconds < 60) {
            return seconds + "秒前";
        } else if (minutes < 60) {
            return minutes + "分钟前";
        } else if (hours < 24) {
            return hours + "小时前";
        } else if (days <= 3) {
            return days + "天前";
        } else {
            return time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }
    }
}
